/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "ui列表.h"

#include "ui文本编辑.h"
#include "ui按钮.h"
#include "UI/UI.h"


static C_下拉列表框*	g当前打开列表组件 = nullptr;
static int32			g项滚动数量 = 4;



static E_事件是否传递 f_列表框鼠标滚轮(C_Widget* self, const S_鼠标& 鼠标) {
	C_列表框* box = dynamic_cast<C_列表框*>(self);
	f_布局_组件纵向滚动(self->m_父部件, self, C_Widget::g_鼠标.lZ * 40);
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_列表框项部件鼠标进入(C_Widget* self, const S_鼠标& 轮值) {
	C_列表框* box = dynamic_cast<C_列表框*>(self->m_父部件);
	self->m_ColorA.m_颜色 += 100;
	box->m_更新绘制属性 = true;
	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_列表框项部件鼠标退出(C_Widget* self, const S_鼠标& 轮值) {
	C_列表框* box = dynamic_cast<C_列表框*>(self->m_父部件);
	self->m_ColorA.m_颜色 = {};
	box->m_更新绘制属性 = true;
	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_列表项选中(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_列表框* box = dynamic_cast<C_列表框*>(self->m_父部件);
	auto* data = (S_列表填充数据*)self->m_UserData;

	for (auto& e : box->m_当前选中项) {
		e->m_激活 = false;
	}


	box->m_当前选中项.clear();
	box->m_当前选中项.push_back(data);

	std::vector<std::u16string> files;
	for (auto& e : box->m_当前选中项) {
		e->m_激活 = true;
		files.push_back(e->m_item.front());
	}
	if(box->mf_项选中回调) box->mf_项选中回调(box, files);


	auto we = box->f_get更新组件();
	for (uint32 i = 0; i < we.m_Num; ++i) {
		we.m_W[i]->m_ColorA.m_颜色 = {};
	}
	box->m_更新绘制属性 = true;
	return E_事件是否传递::e_事件传递_终止;
}

//static bool f_文件项双击选中(C_Widget* self, const E_鼠标按钮& 按钮) {
//	C_列表框* box = dynamic_cast<C_列表框*>(self->m_父部件);
//	
//	box->m_当前选中项.clear();
//	box->m_当前选中项.push_back(self->m_实例ID);
//
//	std::vector<std::u16string> files;
//	for (auto& i : box->m_当前选中项) {
//		auto& e = box->m_列表数据[i];
//		files.push_back(e.m_item[0]);
//	}
//	box->mf_项选中回调(box, files);
//	return true;
//}


static void f_列表框布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_列表框& box = *dynamic_cast<C_列表框*>(self);

	float32 dpi = box.m_UIctx->m_DPI;
	float32 行高 = box.m_行高度 * dpi;

	int32 行开始偏移 = 0;
	box.m_有效行显示数量 = f_ui_Layout_行显示范围(self, 行高, box.m_列表数据.size(), 行开始偏移);


	auto we = self->f_get更新组件();
	for (int32 i = we.m_Num; i < box.m_有效行显示数量; ++i) {
		box.f_添加子组件(box.f_创建项组件());
	}
	
	we = self->f_get更新组件();
	for (uint32 i = 0; i < box.m_有效行显示数量; ++i) {
		we.m_W[i]->f_setPos({0, 行高 * (行开始偏移 + i)});
		we.m_W[i]->f_setSize({self->m_Size.x, 行高});

		we.m_W[i]->m_UserData = &box.m_列表数据[行开始偏移 + i];
	}

	for (int32 i = box.m_有效行显示数量 ; i < we.m_Num; ++i) {
		we.m_W[i]->f_setPos({0, 0});
		we.m_W[i]->f_setSize({0, 0});
	}

}

static void f_列表框绘制(C_Widget* self, S_2D画布* 画布) {
	C_列表框& box = *dynamic_cast<C_列表框*>(self);

	box.m_背景 = f_vg_genConvex((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	box.m_字符 = f_vg_genString((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal, S_UI主题::ui_默认字体);
	box.m_图标 = f_vg_genIco((*self), *画布, E_图层混合模式::e_Normal, E_填充模式::e_填充面, S_UI主题::ui_默认图标);
}


static void f_列表框变换(C_Widget* self) {
	C_列表框& box = *dynamic_cast<C_列表框*>(self); 
	uint32 num = self->f_get子部件数量();
	float32 dpi = box.m_UIctx->m_DPI;

	bool 参数重置 = false;

	std::vector<S_2DConvexRect>	区域;
	std::vector<S_GPU内存块*>	形状;
	std::vector<S_2D颜色包>		颜色;
	std::vector<vec2>			位置;


	std::vector<S_Rect2Df>		标签区域;
	std::vector<S_RGBA8UI>		标签颜色;
	std::vector<std::u16string>	标签字符;

	std::vector<std::u16string>	图标;
	std::vector<vec2>			图标位置;
	std::vector<vec2>			图标大小;
	std::vector<S_2D颜色包>		图标颜色;


	S_2DConvexRect convRect{};
	//convRect.size = rect.extent;


	auto we = self->f_get更新组件();
	for (uint32 i = 0; i < box.m_有效行显示数量; ++i) {
		S_列表填充数据& data = *(S_列表填充数据*)we.m_W[i]->m_UserData;

		auto rect = we.m_W[i]->f_getRect(true);
		
		convRect.size = rect.extent;
		convRect.AA_type = {1,0};
		区域.emplace_back(convRect);
		形状.emplace_back(we.m_W[i]->m_图元形状);
		颜色.emplace_back(data.m_激活 ? S_UI主题::uic_焦点色 : we.m_W[i]->m_ColorA);
		位置.emplace_back(rect.offset);


		float32 icoSize = rect.extent.y*0.5f;
		图标.emplace_back(data.m_ico);
		图标位置.emplace_back(vec2{rect.offset.x + icoSize, rect.offset.y + icoSize});
		图标大小.emplace_back(vec2{ rect.extent.y*0.75f, rect.extent.y*0.75f});
		图标颜色.emplace_back(S_2D颜色包(data.m_ico_color));

		rect.offset.x += rect.extent.y;
		标签区域.emplace_back(rect);
		标签颜色.emplace_back(S_UI主题::uic_文字颜色);
		标签字符.emplace_back(data.m_item.front());

	}



	f_vg_drawConvex(*box.m_背景, 形状.size(), 形状.data(), 区域.data());
	f_vg_tranform(*box.m_背景, 位置.size(), 位置.data());
	f_vg_color(*box.m_背景, 颜色.size(), 颜色.data());

	S_行字符串绘制属性 行字符串绘制属性 = { S_UI主题::ui_文字间隔 * dpi, E_方向::e_横向 };
	f_vg_drawString(*box.m_字符, 标签字符, 标签区域, 标签颜色, E_对齐方式::e_左对齐, 行字符串绘制属性);

	f_vg_drawIco(*box.m_图标, 图标.size(), 图标.data());
	f_vg_tranform(*box.m_图标, 图标位置.size(), 图标位置.data(), 图标大小.data());
	f_vg_color(*box.m_图标, 图标颜色.size(), 图标颜色.data());
}

C_列表框::C_列表框(S_UI渲染环境& ctx, uint8 列数量, E_列表显示模式 模式) : C_Widget(&ctx), m_列数(列数量) {
	m_WName = u"列表框";
	m_TypeName = "C_Widget 列表框";

	m_列表显示模式 = 模式;
	
	f_widget_开启视口属性(this);
	f_widget_添加绘制画布(this);
	mf_鼠标滚轮 = f_列表框鼠标滚轮;
	
	mf_绘制 = f_列表框绘制;
	mf_布局 = f_列表框布局;
	mf_变换 = f_列表框变换;

	m_是否多选 = false;
	mf_项选中回调 = nullptr;
	m_有效行显示数量 = 0;

	//const auto& font = f_surface_get字体库(ctx, S_UI主题::ui_默认字体);
	m_行高度 = uint32(24 * ctx.m_DPI);

	m_ColorA = S_UI主题::uic_列表行A;
	m_ColorA.m_模式 = DEF_2DShaderType_Stripe;
	m_颜色A = S_UI主题::uic_列表行A;
	m_颜色B = S_UI主题::uic_列表行B;
}

C_列表框::~C_列表框() {
}


C_Widget* C_列表框::f_创建项组件() {
	C_Widget* item = new C_Widget(m_UIctx);

	item->mf_鼠标进入 = on_列表框项部件鼠标进入;
	item->mf_鼠标离开 = on_列表框项部件鼠标退出;
	item->mf_鼠标点击 = on_列表项选中;
	item->m_ColorA = {};

	return item;
}

void C_列表框::f_填充列表(std::vector<S_列表填充数据>& data) {
	m_列表数据 = data;

	uint32 num = data.size();
	uint32 oldNum = m_子组件.size();

	if (num > oldNum) {
		for (uint32 i = oldNum; i < num; ++i) {
			C_Widget* item = f_创建项组件();
			f_添加子组件(item);
		}
	} else if (oldNum > num) {
		for (uint32 i = num; i < oldNum; ++i) {
			f_销毁子组件(-1);
		}
	}

	for (uint32 i = 0; i < num; ++i) {
		//f_addItem(data[i], i);
		m_列表数据[i] = data[i];

	}

	m_当前选中项.clear();
	m_Size.y = num * m_行高度;
	f_setY(0);
	m_更新绘制属性 = true;
}

C_Widget* C_列表框::f_addItem(const S_列表填充数据& data, uint32 offset) {
	
	uint32 oldNum = m_子组件.size();
	if (offset >= m_列表数据.size()) {
		m_列表数据.push_back(data);

		C_Widget* item = f_创建项组件();
		f_添加子组件(item);

		return item;
	}
	else {
		m_列表数据[offset] = data;
	}
	return nullptr;
}

void C_列表框::f_delItem(S_列表填充数据& data, uint32 offset) {
	
}

void C_列表框::f_clearItem() {
	f_widget_remove区间子组件(this, 0, m_列表数据.size());
	m_列表数据.clear();
	m_当前选中项.clear();
}

std::vector<std::string> C_列表框::f_构建选中文件(std::string root) {
	std::vector<std::string> files;

	if (root.back() != 47 && root.back() != 92) {
		root += '/';
	}

	uint32 offset = 0;
	for (auto& e : m_当前选中项) {
		files.push_back(root + f_str_u16_to_u8(e->m_item.front()));
	}

	return files;
}


void f_ui_列表框_添加列表项(C_Widget* self, const S_列表填充数据& data, int32 位置) {
	C_列表框& box = *static_cast<C_列表框*>(self);

	box.m_当前选中项.clear();
	if (uint32(位置) >= box.m_列表数据.size()) {
		位置 = box.m_列表数据.size();
		box.m_列表数据.push_back(data);
	}
	else {
		box.m_列表数据.insert(box.m_列表数据.begin() + 位置, data);
	}
	box.m_当前选中项[位置] = &box.m_列表数据[位置];
	
	C_Widget* item = box.f_创建项组件();
	box.f_添加子组件(item, 位置);

	
	if(box.mf_项选中回调) box.mf_项选中回调(&box, box.m_列表数据[位置].m_item);
}

int32 f_ui_列表框_移除列表项(C_Widget* self, int32 位置) {
	C_列表框* box = static_cast<C_列表框*>(self);

	if (!box->m_列表数据.size()) {
		return -1;
	}
	if (uint32(位置) >= box->m_列表数据.size()) {
		box->m_列表数据.pop_back();
	}
	else {
		box->m_列表数据.erase(box->m_列表数据.begin() + 位置);
	}

	box->m_当前选中项.clear();

	box->f_销毁子组件(位置);
	
	auto e = box->f_get更新组件();
	for (uint32 i = 0; i < e.m_Num; ++i) {
		e.m_W[i]->m_实例ID = i;
	}

	box->f_setH(e.m_Num * box->m_行高度);

	if (位置 >= box->m_列表数据.size()) {
		位置 = box->m_列表数据.size() - 1;
	}
	if(box->mf_项选中回调 && 位置 >= 0) box->mf_项选中回调(box, box->m_列表数据[位置].m_item);
	return e.m_Num;
}

void f_ui_列表框_填充(C_Widget* self, const std::vector<S_列表填充数据>& data) {
	C_列表框* box = static_cast<C_列表框*>(self);

	f_ui_列表框_删除项(self, -1);


	box->m_当前选中项.clear();
	box->m_列表数据.clear();
	box->m_列表数据 = data;

	uint32 num = data.size();
	if(!num) {
		box->f_setH(box->m_行高度);
		return;
	}
	box->m_当前选中项.push_back(0);

	
	for (uint32 i = 0; i < num; ++i) {
		C_Widget* item = new C_Widget;
		item->mf_鼠标进入 = on_列表框项部件鼠标进入;
		item->mf_鼠标离开 = on_列表框项部件鼠标退出;
		item->mf_鼠标点击 = on_列表项选中;
		item->m_实例ID = box->f_get子部件数量();

		box->f_添加子组件(item);
	}
	box->f_setH(num * box->m_行高度);

	if(box->mf_项选中回调) box->mf_项选中回调(box, box->m_列表数据[0].m_item);
}

int32 f_ui_列表框_取当前选中ID(C_Widget* self) {
	C_列表框& box = *static_cast<C_列表框*>(self);
	if (box.m_当前选中项.size()) {
		return std::distance(box.m_当前选中项.begin(), box.m_当前选中项.begin());
	}
	uint32 num = box.m_列表数据.size();
	if (num) return num - 1;
	return -1;
}

S_列表填充数据& f_ui_列表框_取当前选中项(C_Widget* self) {
	C_列表框& box = *static_cast<C_列表框*>(self);
	if (box.m_当前选中项.size()) {
		
		return *box.m_当前选中项.front();
	}
	static S_列表填充数据 temp{};
	return temp;
}

S_列表填充数据 f_ui_列表框_取选(C_Widget* self, int32 id) {
	C_列表框* box = static_cast<C_列表框*>(self);
	if (id >= box->m_列表数据.size()) {
		return {};
	}
	return box->m_列表数据[id];
}

uint32 f_ui_列表框_删除项(C_Widget* self, int32 s, int32 e) {
	C_列表框* box = static_cast<C_列表框*>(self);
	if (s < 0) {
		box->f_clearItem();
	}

	box->f_setH( box->m_行高度);
	return 0;
}

void f_ui_列表框_设置项(C_Widget* self, int32 位置, const S_列表填充数据& data) {
	C_列表框* box = static_cast<C_列表框*>(self);

	if (位置 >= box->m_列表数据.size()) 位置 = box->m_列表数据.size() - 1;

	box->m_列表数据[位置] = data;
	box->m_子组件[位置]->m_更新绘制属性 = true;
	box->m_更新绘制属性 = true;
}

uint32 f_ui_列表框_取项数量(C_Widget* self) {
	C_列表框* box = static_cast<C_列表框*>(self);
	return box->m_列表数据.size();
}

void f_ui_列表框_绑定项选中回调(C_Widget* self, fp_列表项选中回调_str call) {
	C_列表框* box = static_cast<C_列表框*>(self);
	box->mf_项选中回调 = call;
}

void f_ui_列表框_关闭项选择清除(C_Widget* self) {
	C_列表框* box = static_cast<C_列表框*>(self);
	
}





static void on_滚动框_布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_列表框* box = dynamic_cast<C_列表框*>(w[0]);
	float32 dpi = self->m_UIctx->m_DPI;

	uint32 itemNum = box->m_列表数据.size();
	box->f_setH(max(itemNum * box->m_行高度 * dpi, self->m_Size.y));
	box->f_setW(self->m_Size.x);

	f_布局_扩展视口纵向滚动(self, w[0], 0);
}

static void on_滚动框_绘制(C_Widget* self, S_2D画布* 画布) {
	auto* 背景 = f_vg_genConvex((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
}

static void on_滚动框_变换(C_Widget* self) {
	C_列表框& 列表框 = *dynamic_cast<C_列表框*>(self->f_get子组件(0));

	float32 dpi = self->m_UIctx->m_DPI;
	S_Surface2D* m_背景 = f_widget_getSurface2D(self, 0);

	std::vector<S_2DConvexRect>	区域;
	std::vector<S_GPU内存块*>	形状;
	std::vector<S_2D颜色包>		颜色;
	std::vector<vec2>			位置;

	S_2DConvexRect rect{};
	rect.offset = { dpi * 列表框.m_行高度, self->m_Pos.y + 列表框.m_Pos.y};
	rect.size = self->m_Size;
	rect.AA_type = {1, DEF_2DShaderType_Stripe };
	区域.emplace_back(rect);
	位置.emplace_back(vec2{});
	颜色.emplace_back(列表框.m_ColorA);
	形状.emplace_back(&self->m_UIctx->m_Ctx.m_几何图形->m_平面圆角矩形);

	f_vg_drawConvex(*m_背景, 区域.size(), 形状.data(), 区域.data());
	f_vg_tranform(*m_背景, 位置.size(), 位置.data());
	f_vg_color(*m_背景, 颜色.size(), 颜色.data());
}

C_Widget* f_ui_创建列表(S_UI渲染环境& ctx, E_列表显示模式 模式) {
	C_列表框* listbox = new C_列表框(ctx, 1, 模式);

	C_滚动框* box = new C_滚动框(ctx, true, true, listbox);
	box->mf_布局 = on_滚动框_布局;
	box->mf_绘制 = on_滚动框_绘制;
	box->mf_变换 = on_滚动框_变换;
	f_widget_添加绘制画布(box);
	return box;
}











static void f_下拉列表布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_下拉列表框* box = static_cast<C_下拉列表框*>(self);
	
	float32 size = self->m_Size.y;

	auto e = self->f_get更新组件();
	e.m_W[0]->f_setSize({ size, size });
	e.m_W[1]->f_setSize({ size, size });
	e.m_W[2]->f_setSize({ size, size });
	e.m_W[3]->f_setSize({ size, size });

	e.m_W[0]->m_是否延展 = { false, false };
	e.m_W[1]->m_是否延展 = { true, true };
	e.m_W[2]->m_是否延展 = { false, false };
	e.m_W[3]->m_是否延展 = { false, false };
	f_HBOX布局(self, e.m_W, e.m_Num);
}

static void f_draw下拉列表(C_Widget* self, S_2D画布* 画布) {
	C_下拉列表框* box = static_cast<C_下拉列表框*>(self);
	self->m_绘图模板.clear();

	//box->m_背景绘制.m_属性 = f_vg_gen属性(画布);
	//
	//S_凸边图元 图元 = {};
	//图元.属性 = f_vg_get属性指针(画布, box->m_背景绘制.m_属性);
	//box->m_背景绘制.f_Draw(画布, 图元, E_笔刷类型::e_单色填充);
	////box->m_文字绘制.f_Draw文本(画布, self->m_UIctx->m_文字字号, gDraw列表框_属性ID);
	//box->m_图标绘制.f_Draw单色(画布, box->m_背景绘制.m_属性, S_UI主题::ui_默认图标);
	//
	//self->m_绘图模板.push_back(&box->m_背景绘制);
	//self->m_绘图模板.push_back(&box->m_图标绘制);
}


//static void f_下拉列表变换修改(C_Widget* self, mat3X2** t, uint16 num) {
//	C_下拉列表框* box = static_cast<C_下拉列表框*>(self);
//	bool 参数重置 = false;
//
//	S_2D顶点属性 属性;
//	属性.m_比例 = { 1,1 };
//	属性.m_偏移 = {};
//	属性.m_间隔 = S_UI主题::ui_文字间隔;
//	属性.m_渐变数量 = 0;
//	f_vg_set属性(box->m_画布, gDraw列表框_属性ID, 属性);
//
//
//	S_LineProp 线属性 = { 1.0, f_PackData4X8(box->m_颜色A), f_PackData4X8(box->m_颜色B)};
//
//	box->m_背景绘制.f_alloc(1);
//	mat3X2 mat;
//	mat.row0 = { 0,0 };
//	mat.row1 = self->m_Size;
//	mat.row2 = { S_UI主题::ui_面板圆角半径, 0 };
//	box->m_背景绘制.f_set单色线(3, mat, 线属性, S_Widget预设图元::m_圆角矩形);
//
//	auto e = self->f_get更新部件();
//	mat.row0 = e.m_W[0]->m_Pos;
//	mat.row1 = e.m_W[0]->m_Size;
//	mat.row2 = { S_UI主题::ui_面板圆角半径, 0};
//	box->m_背景绘制.f_set单色填充(0, mat, S_UI主题::uic_面板边, S_Widget预设图元::m_左圆角矩形);
//
//	mat.row0 = e.m_W[2]->m_Pos;
//	mat.row1 = e.m_W[2]->m_Size;
//	mat.row2 = { S_UI主题::ui_面板圆角半径, 0 };
//	box->m_背景绘制.f_set单色填充(0, mat, S_UI主题::uic_面板边, S_Widget预设图元::m_矩形);
//
//	mat.row0 = e.m_W[2]->m_Pos;
//	mat.row1 = e.m_W[2]->m_Size;
//	mat.row2 = { S_UI主题::ui_面板圆角半径, 0 };
//	box->m_背景绘制.f_set单色填充(0, mat, S_UI主题::uic_面板边, S_Widget预设图元::m_右圆角矩形);
//
//
//
//
//	box->m_图标绘制.f_alloc(e.m_Num);
//	mat.row0 = e.m_W[0]->m_Pos + e.m_W[0]->m_Size.y * 0.5;
//	mat.row1.x = mat.row1.y = e.m_W[0]->m_Size.y * 0.8f;
//	mat.row2 = {};
//	box->m_图标绘制.f_set("", 0, mat, S_UI主题::uic_深白);
//	
//	//const auto& 字体 = f_surface_get字体库(*self->m_UIctx, S_UI主题::ui_默认字体);
//}







static E_事件是否传递 on_下拉列表部件鼠标进入(C_Widget* self, const S_鼠标& 轮值) {
	C_列表框* box = dynamic_cast<C_列表框*>(self->m_父部件);

	vec2 size = { box->m_Size.x, float32(box->m_行高度) };
	uint32 选中数量 = box->m_当前选中项.size();

	//box->m_当前选项焦点绘制.f_alloc(选中数量 + 1);
	//
	//mat3X2 mat;
	//mat.row0 = self->m_Pos - box->m_扩展视口属性->m_中心;
	//mat.row1 = size;
	//mat.row2 = { S_UI主题::ui_面板圆角半径, 0 };
	//box->m_当前选项焦点绘制.f_set单色填充(选中数量, mat, S_UI主题::uic_菜单焦点色 + S_RGBA8UI{40,40,40,0}, S_Widget预设凸包图元::m_圆角矩形);


	//auto& prop = f_prop_MapPrt(box->m_列表项);
	/*auto e = box->f_get更新部件();
	for (uint32 i = 0; i < 选中数量; ++i) {
		uint32 id = box->m_当前选中项[i];
		mat.row0 = e.m_W[id]->m_Pos;
		mat.row1 = e.m_W[id]->m_Size;
		mat.row2 = { S_UI主题::ui_面板圆角半径, 0 };
		box->m_当前选项焦点绘制.f_set单色填充(i, mat, S_UI主题::uic_菜单焦点色, S_Widget预设图元::m_圆角矩形);
	}*/


	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_下拉列表部件鼠标退出(C_Widget* self, const S_鼠标& 轮值) {
	C_列表框* 父部件 = dynamic_cast<C_列表框*>(self->m_父部件);
	return E_事件是否传递::e_事件传递_继续;
}


static E_事件是否传递 on_下拉列表按钮鼠标进入(C_Widget* self, const S_鼠标& 鼠标) {
	self->m_颜色A = self->m_颜色A + S_RGBA8UI{50, 50, 50, 127};
	self->m_父部件->m_更新绘制属性 = true;
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_下拉列表按钮鼠标退出(C_Widget* self, const S_鼠标& 鼠标) {
	self->m_颜色A = self->m_颜色B;
	self->m_父部件->m_更新绘制属性 = true;
	return E_事件是否传递::e_事件传递_终止;
}

static void on_列表项操作默认函数(S_Props& prop) {

}

static E_事件是否传递 on_打开下拉列表(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_下拉列表框* box = static_cast<C_下拉列表框*>(self->m_父部件);
	if (!box->m_列表项.m_Type) return E_事件是否传递::e_事件传递_终止;

	g当前打开列表组件 = box;

	box->m_列表->f_clearItem();
	auto& prop = f_prop_MapPrt(box->m_列表项);
	for (auto& e : prop.m_PtrItem) {
		C_Widget* item = box->m_列表->f_addItem({ u"", {}, { e.m_Str } }, -1);
		item->mf_鼠标进入 = on_下拉列表部件鼠标进入;
	}


	f_widget_顶层窗口_pop(f_ui_当前窗口管理(), 0);
	f_widget_top_push(f_ui_当前窗口管理(), box->m_列表视口);

	box->m_列表视口->f_setSize({ 200, float32(prop.m_PtrItem.size() * box->m_列表->m_行高度) });
	box->m_列表->f_setSize({ 200, float32(prop.m_PtrItem.size() * box->m_列表->m_行高度) });

	


	vec2 pos = self->m_GlobalLoc;
	pos.y -= (box->m_列表视口->m_Size.y + self->m_Size.y);
	
	f_widget_限制组件大小(box->m_列表视口);
	pos = f_widget_弹出窗口坐标矫正(box->m_列表视口, pos);

	box->m_列表视口->f_setPos(pos);
	//box->m_列表视口->m_GlobalLoc = {256,256};
	f_widget_单个部件裁剪(box->m_列表视口, { pos.x, pos.y, pos.x + box->m_列表视口->m_Size.x, pos.y + box->m_列表视口->m_Size.y }, {});
	box->m_列表视口->m_更新绘制属性 = true;
	box->m_列表->m_更新绘制属性 = true;
	return E_事件是否传递::e_事件传递_终止;
}

static bool on_下拉列表项选中回调(C_Widget* self, const std::vector<std::u16string>& name) {
	C_列表框& box = *static_cast<C_列表框*>(self);
	
	C_行编辑框* editbox = static_cast<C_行编辑框*>(g当前打开列表组件->m_文本编辑框);

	if (box.m_当前选中项.size()) {
		//uint32 ID = box.m_当前选中项.back();
		auto& prop = f_prop_MapPrt(g当前打开列表组件->m_列表项);
		//prop.m_当前项 = ID;
		
		//auto str = prop.m_PtrItem[ID].m_Str;
		//editbox->f_填充文本(str);

		assert(prop.mf_元素变更);
		//prop.mf_元素变更(g当前打开列表组件->m_列表项, prop, ID + E_Prop_MapPtr_项事件类型::e_项选择);
	}
	
	f_widget_top_close(f_ui_当前窗口管理());

	g当前打开列表组件 = nullptr;
	return true;
}

static E_事件是否传递 on_下拉列表添加项(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_下拉列表框* box = static_cast<C_下拉列表框*>(self->m_父部件);
	if (!box->m_列表项.m_Type) return E_事件是否传递::e_事件传递_终止;

	auto& prop = f_prop_MapPrt(box->m_列表项);
	if (prop.mf_元素变更) {
		prop.mf_元素变更(box->m_列表项, prop, E_Prop_MapPtr_项事件类型::e_项添加);

		C_列表框* listBox = static_cast<C_列表框*>(box->m_列表);
		//C_Widget* item = listBox->f_addItem({ "", {}, { *prop.m_PtrItem.back().m_Str } }, -1);
		C_Widget* item = listBox->f_addItem({ u"", {}, { prop.m_PtrItem.back().m_Str } }, -1);
		prop.m_当前项 = prop.m_PtrItem.size() - 1;
		item->mf_鼠标进入 = on_下拉列表部件鼠标进入;
		item->mf_鼠标离开 = on_下拉列表部件鼠标退出;

		C_行编辑框* editbox = static_cast<C_行编辑框*>(box->m_文本编辑框);
		//editbox->f_set文本(*prop.m_PtrItem.back().m_Str);
		editbox->f_填充文本(prop.m_PtrItem[prop.m_当前项].m_Str);

		box->m_列表视口->f_setSize({ 200, prop.m_PtrItem.size() * 24.0f });
	}

	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_下拉列表移除项(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_下拉列表框* box = static_cast<C_下拉列表框*>(self->m_父部件);
	if (!box->m_列表项.m_Type) return E_事件是否传递::e_事件传递_终止;

	auto& prop = f_prop_MapPrt(box->m_列表项);
	if (prop.mf_元素变更) {
		prop.mf_元素变更(box->m_列表项, prop, E_Prop_MapPtr_项事件类型::e_项删除);

		if (prop.m_PtrItem.size()) {
			C_行编辑框* editbox = static_cast<C_行编辑框*>(box->m_文本编辑框);
			editbox->f_填充文本(prop.m_PtrItem[prop.m_当前项].m_Str);
		}
	}
	return E_事件是否传递::e_事件传递_终止;
}


static E_事件是否传递 on_列表视口鼠标进入(C_Widget* self, const S_鼠标& 轮值) {
	//C_菜单* pMenu = dynamic_cast<C_菜单*>(menu->m_父部件);
	C_Widget::g_是否打开了弹出窗口 = false;
	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_列表视口鼠标移出(C_Widget* self, const S_鼠标& 轮值) {
	C_下拉列表框* box = static_cast<C_下拉列表框*>(self->m_父部件);
	C_Widget::g_是否打开了弹出窗口 = true;
	//创建线程
	f_widget_线程定时关闭弹出组件();
	//auto hThread = CreateThread(NULL, 0, f_widget_定时关闭弹出组件, NULL, 0, NULL);
	return E_事件是否传递::e_事件传递_继续;
}

static void on_Widget文本输入完成(C_Widget* self) {
	C_行编辑框* editbox = static_cast<C_行编辑框*>(self);
	C_下拉列表框* box = static_cast<C_下拉列表框*>(self->m_父部件);
	if (!box->m_列表项.m_Type) return;

	auto& prop = f_prop_MapPrt(box->m_列表项);
	//*(prop.m_PtrItem[prop.m_当前项].m_Str) = editbox->m_Text;
	prop.m_PtrItem[prop.m_当前项].m_Str = editbox->m_Text;
	if (prop.mf_元素变更) {
		prop.mf_元素变更(box->m_列表项, prop, E_Prop_MapPtr_项事件类型::e_项名称改变);
	}
}

static void on_下拉列表_滚动框布局(C_Widget* self, C_Widget** w, uint32 num) {
	w[0]->f_setW(self->m_Size.x);
}

C_下拉列表框::C_下拉列表框(S_UI渲染环境& ctx, bool 可编辑) : C_Widget(&ctx) {
	C_Widget* 弹出菜单按钮 = new C_Widget;
	弹出菜单按钮->f_setSize({ 24,24 });
	弹出菜单按钮->mf_鼠标进入 = on_下拉列表按钮鼠标进入;
	弹出菜单按钮->mf_鼠标离开 = on_下拉列表按钮鼠标退出;
	弹出菜单按钮->m_颜色A = S_UI主题::uic_按钮;
	弹出菜单按钮->m_颜色B = S_UI主题::uic_按钮;
	弹出菜单按钮->m_图元形状 = &m_UIctx->m_Ctx.m_几何图形->m_平面左圆角矩形;
	f_添加子组件(弹出菜单按钮);

	

	m_文本编辑框 = new C_行编辑框(ctx);
	m_文本编辑框->mf_鼠标进入 = on_下拉列表按钮鼠标进入;
	m_文本编辑框->mf_鼠标离开 = on_下拉列表按钮鼠标退出;
	((C_行编辑框*)m_文本编辑框)->mf_文本完成 = on_Widget文本输入完成;
	f_添加子组件(m_文本编辑框);
	


	C_Widget* 添加项按钮 = new C_Widget;
	添加项按钮->f_setSize({ 24,24 });
	添加项按钮->mf_鼠标进入 = on_下拉列表按钮鼠标进入;
	添加项按钮->mf_鼠标离开 = on_下拉列表按钮鼠标退出;
	添加项按钮->m_颜色A = S_UI主题::uic_按钮;
	添加项按钮->m_颜色B = S_UI主题::uic_按钮;
	添加项按钮->m_图元形状 = &m_UIctx->m_Ctx.m_几何图形->m_平面矩形;

	m_移除项按钮 = new C_Widget;
	m_移除项按钮->f_setSize({ 24,24 });
	m_移除项按钮->mf_鼠标进入 = on_下拉列表按钮鼠标进入;
	m_移除项按钮->mf_鼠标离开 = on_下拉列表按钮鼠标退出;
	m_移除项按钮->m_颜色A = S_UI主题::uic_按钮;
	m_移除项按钮->m_颜色B = S_UI主题::uic_按钮;
	m_移除项按钮->m_图元形状 = &m_UIctx->m_Ctx.m_几何图形->m_平面右圆角矩形;

	f_添加子组件(添加项按钮);
	f_添加子组件(m_移除项按钮);

	mf_绘制 = f_draw下拉列表;
	mf_布局 = f_下拉列表布局;


	弹出菜单按钮->mf_鼠标按键按下 = on_打开下拉列表;
	if (可编辑) {
		添加项按钮->mf_鼠标按键按下 = on_下拉列表添加项;
		m_移除项按钮->mf_鼠标按键按下 = on_下拉列表移除项;
	}


	m_列表 = new C_列表框(ctx, 1, E_列表显示模式::e_列表模式_垂直);
	m_列表->mf_项选中回调 = on_下拉列表项选中回调;
	m_列表->f_setSize({ 256, 512 });

	m_列表视口 = new C_滚动框(ctx, false, true, m_列表);
	m_列表视口->f_setSize({ 256, 512 });
	m_列表视口->mf_鼠标进入 = on_列表视口鼠标进入;
	m_列表视口->mf_鼠标离开 = on_列表视口鼠标移出;
	//m_列表视口->mf_鼠标滚轮 = f_列表框鼠标滚轮;
	m_列表视口->mf_鼠标滚轮 = nullptr;
	m_列表视口->mf_布局 = on_下拉列表_滚动框布局;

	mf_添加项 = on_列表项操作默认函数;
	mf_移除项 = on_列表项操作默认函数;
}

C_下拉列表框::~C_下拉列表框(){
}


C_Widget* f_ui_创建下拉列表(S_UI渲染环境& ctx, bool 可编辑, bool 拷贝按钮) {
	C_下拉列表框* box = new C_下拉列表框(ctx, 可编辑);

	if (拷贝按钮) {
		box->m_移除项按钮->m_ICO = u"clipboard_copy";
	}
	else {
		box->m_移除项按钮->m_ICO = u"删除";
	}

	return box;
}

void f_ui_绑定下拉列表属性(C_Widget* self, S_Props& prop) {
	C_下拉列表框* listbox = static_cast<C_下拉列表框*>(self);
	listbox->m_列表项 = prop;
	listbox->m_文本编辑框->f_bind属性(prop);

	C_列表框* listBox = static_cast<C_列表框*>(listbox->m_列表);
	listBox->f_clearItem();

	auto& p = f_prop_MapPrt(prop);
	uint32 num = p.m_PtrItem.size();
	if (num) {
		if (p.m_当前项 >= num) p.m_当前项 = 0;
		//auto& str = *p.m_PtrItem[p.m_当前项].m_Str;
		auto& str = p.m_PtrItem[p.m_当前项].m_Str;
		static_cast<C_行编辑框*>(listbox->m_文本编辑框)->f_填充文本(str);


		listbox->m_列表->f_clearItem();
		for (auto& e : p.m_PtrItem) {
			C_Widget* item = listbox->m_列表->f_addItem({ u"", {}, { e.m_Str } }, -1);
			item->mf_鼠标进入 = on_下拉列表部件鼠标进入;
		}
	}
	
}

void f_ui_设置下拉列表项(C_Widget* self, int32 id) {
	C_下拉列表框* listbox = static_cast<C_下拉列表框*>(self);
	
	if (id >= 0) {
		auto item = f_ui_列表框_取选(listbox->m_列表, id);
		if (item.m_item.size()) {
			static_cast<C_行编辑框*>(listbox->m_文本编辑框)->m_Text = item.m_item[0];
		}
	}
	else {
		static_cast<C_行编辑框*>(listbox->m_文本编辑框)->m_Text = u"";
	}
	listbox->m_文本编辑框->m_更新绘制属性 = true;
}

std::u16string f_ui_get下拉列表文本(C_Widget* self) {
	C_下拉列表框* listbox = static_cast<C_下拉列表框*>(self);
	return static_cast<C_行编辑框*>(listbox->m_文本编辑框)->m_Text;
}








int32 f_ui_树形框_层级组件步进(S_Object* item, int32& 行开始偏移, C_Widget** widget, uint32 num, uint32& index) {
	if (行开始偏移 > 0) {
		--行开始偏移;
	}
	else if (index < num) {
		widget[index]->m_UserData = item;
		++index;
	}
	else {
		return 0;
	}
	return 1;
}

static float32 f_树形框_项显示范围计算(C_树形框* tree, S_Object* item, int32 缩进, int32& 行开始偏移, C_Widget** w, uint32 num, uint32& index, float32 行高) {
	float32 h = 0;
	uint32 子项数量 = item->m_子物体.size();

	int32 累计项 = f_ui_树形框_层级组件步进(item, 行开始偏移, w, num, index);

	if (累计项) {
		if (item->m_是否展开) {
			for (auto& e : item->m_子物体) {
				h += f_树形框_项显示范围计算(tree, e, 缩进 + 1, 行开始偏移, w, num, index, 行高);
			}

			if (tree->mf_自定义子项层级范围计算) {
				h += tree->mf_自定义子项层级范围计算(item, 缩进 + 1, 行开始偏移, w, num, index) * 行高;
			}

			h += 行高 * 子项数量;
		}
		if (行开始偏移 <= 0) {
			item->m_层深度 = 缩进;
			item->m_层数量 = h;
		}
	}
	return h;
}

static bool f_树形框_项区间选择(S_Object* root, S_Object* item_end) {
	auto em = root->m_子物体.data();
	uint32 num = root->m_子物体.size();

	for (uint32 i = 0; i < num; ++i) {
		em[i]->m_选中 = true;

		if(em[i] == item_end) return true;
		if (em[i]->m_是否展开 && !root->m_子物体.empty()) {
			if (f_树形框_项区间选择(em[i], item_end)) {
				return true;
			}
		}
	}
	return false;
}

static E_事件是否传递 on_树形框项鼠标点击(C_Widget* self, const E_鼠标按钮& 按钮) {
	auto& box = *static_cast<C_树形框*>(self->m_父部件);
	
	if (self->m_UserData) {
		auto e = box.f_get更新组件();
		for (uint32 i = 0; i < e.m_Num; ++i) {
			e.m_W[i]->m_颜色A = {};
		}

		assert(self->m_UserData);
		if (box.m_清除选项) {
			box.m_选择项 = { (S_Object*)self->m_UserData };
		}
		else {
			if (box.m_选择项.size()) {
				S_Object* item_begin;
				S_Object* item_end;

				if (self->m_Pos.y >= box.m_当前选择项位置.y) {
					item_begin = box.m_当前选择项;
					item_end = (S_Object*)self->m_UserData;
				}
				else {
					item_begin = (S_Object*)self->m_UserData;
					item_end = box.m_当前选择项;
				}
			}
		}
		
		box.m_当前选择项位置 = self->m_Pos;
		box.m_当前选择项 = (S_Object*)self->m_UserData;

		self->m_颜色A = S_UI主题::uic_焦点色;
	}
	
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_树形框项鼠标进入(C_Widget* self, const S_鼠标& 鼠标) {
	C_树形框& box = *static_cast<C_树形框*>(self->m_父部件);

	S_2DConvexRect rect{};
	rect.radius = { 4,4 };
	rect.AA_type = { f_PackData4X8({20,20,20,20}), 0 };

	return E_事件是否传递::e_事件传递_终止;
}
static E_事件是否传递 on_树形框鼠标离开(C_Widget* self, const S_鼠标& 鼠标) {
	C_树形框& box = *static_cast<C_树形框*>(self);
	return E_事件是否传递::e_事件传递_终止;
}

float32 f_ui_树形框_构建区域项显示(C_Widget* self) {
	auto& box = *static_cast<C_树形框*>(self);
	const float32 dpi = self->m_UIctx->m_DPI;

	float32 行高 = box.m_行高度 * dpi;

	uint32 组件数量 = self->m_父部件->m_Size.y / 行高 + g项滚动数量;
	uint32 num = self->f_get子部件数量();

	for (uint32 i = num; i < 组件数量; ++i) {
		C_Widget* item = new C_Widget;

		item->mf_鼠标点击 = on_树形框项鼠标点击;
		item->mf_鼠标进入 = on_树形框项鼠标进入;
		self->f_添加子组件(item);
	}
	


	auto e = box.f_get更新组件();

	vec2 pos = box.m_Pos;
	int32 行开始偏移 = pos.y <= 0 ? abs(pos.y) / 行高 : 0;

	float32 高度 = 0;
	box.m_有效行数 = 0;
	
	if (组件数量) {
		高度 += f_树形框_项显示范围计算(&box, box.m_Data, 0, 行开始偏移, e.m_W, e.m_Num, box.m_有效行数, 行高);
	}


	for (uint32 i = 0; i < 组件数量; ++i) {
		if (i < box.m_有效行数) {
			if (box.mf_项附件组件创建 && e.m_W[i]->m_UserData) {
				box.mf_项附件组件创建(*box.m_UIctx, e.m_W[i]);
			}
		}
		else {
			e.m_W[i]->m_UserData = nullptr;
		}
	}

	self->f_setH(高度 + 行高 * 3);

	f_widget_更新绘制(self);
	return self->m_Size.y;
}

void f_ui_树形框_清除(C_Widget* self) {
	auto& box = *static_cast<C_树形框*>(self);

	for (auto& e : box.m_子组件) {
		e->m_UserData = nullptr;
	}
	box.m_有效行数 = 0;
	box.m_选择项.clear();
	box.m_当前选择项 = nullptr;
	

	f_widget_remove所有子部件(self, false);
	f_widget_更新绘制(self);
}

static void f_树形框_重置选择项(C_树形框* tree, S_Object* item) {
	for (auto& e : item->m_子物体) {
		if (e->m_选中) {
			assert(e);
			tree->m_选择项.emplace_back(e);
		}
		f_树形框_重置选择项(tree, e);
	}
}


static void f_树形框布局(C_Widget* self, C_Widget** w, uint32 num) {
	auto& box = *static_cast<C_树形框*>(self);
	const float32 dpi = self->m_UIctx->m_DPI;

	float32 行高 = box.m_行高度 * dpi;
	vec2 size = { box.m_Size.x, float32(行高) };
	
	auto e = self->f_get更新组件();
	if (e.m_Num) {
		vec2 pos = box.m_Pos;
		int32 行开始偏移 = pos.y <= 0 ? abs(pos.y) / 行高 : 0;

		if (pos.y <= 0) {
			pos.y += 行开始偏移 * 行高;
		}
		pos.y = 行开始偏移 * 行高;


		for (uint32 i = 0; i < e.m_Num; ++i) {
			S_Object* item = (S_Object*)e.m_W[i]->m_UserData;

			e.m_W[i]->f_setPos(pos);
			e.m_W[i]->f_setSize(size);
			

			if (i >= box.m_有效行数) {
				e.m_W[i]->m_UserData = nullptr;
			}
			else {
				e.m_W[i]->m_WName = item->m_Name;
				f_widget_更新绘制(e.m_W[i]);
			}

			pos.y += 行高;
		}
	}
}

static void f_树形框绘制(C_Widget* self, S_2D画布* 画布) {
	C_树形框& box = *dynamic_cast<C_树形框*>(self);

	box.m_背景 = f_vg_genConvex((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	box.m_线 = f_vg_genLine((*self), *画布, E_图层混合模式::e_Normal, E_线类型::e_连续线);
	box.m_标签 = f_vg_genString((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal, u"雅黑");
	box.m_图标 = f_vg_genIco((*self), *画布, E_图层混合模式::e_Normal, E_填充模式::e_填充面);

}

static void f_树形框变换修改(C_Widget* self) {
	C_树形框& box = *static_cast<C_树形框*>(self);
	uint32 num = self->f_get子部件数量();
	auto e = self->f_get更新组件();


	std::vector<S_2DConvexRect>	区域;
	std::vector<S_GPU内存块*>	形状;
	std::vector<S_2D颜色包>		颜色;
	std::vector<vec2>			位置;

	std::vector<std::u16string> 字符文本;
	std::vector<S_Rect2Df>		字符区域;
	std::vector<S_RGBA8UI>		字符颜色;

	std::vector<std::u16string> 图标名称;
	std::vector<S_RGBA8UI>		图标颜色;
	std::vector<vec2>			图标位置;
	std::vector<vec2>			图标大小;
	
	const float32 dpi = self->m_UIctx->m_DPI;

	float32 行高 = box.m_行高度 * dpi;
	float32 ico_offset = 行高 * 0.5;
	int32 开始推进 = 0;
	int32 线使用量 = -1;

	box.m_直线坐标.clear();
	box.m_直线坐标.reserve(box.m_有效行数);



	for (uint32 i = 0; i < box.m_有效行数; ++i) {
		S_Object* item = ((S_Object*)e.m_W[i]->m_UserData);

		float32 高度 = item->m_层数量;
		float32 推进 = item->m_层深度 * 行高;
		vec2 coord = e.m_W[i]->m_Pos;


		auto 子组件 = e.m_W[i]->f_get更新组件();
		for (uint32 k = 0; k < 子组件.m_Num; ++k) {
			auto* icoWidget = 子组件.m_W[k];
			vec2 图标坐标 = coord + icoWidget->m_Pos + ico_offset;
			图标名称.push_back(icoWidget->m_ICO);
			图标颜色.push_back(S_UI主题::uic_单色图标);
			图标位置.push_back(图标坐标);
			图标大小.push_back(_Vec2(icoWidget->m_图标大小) * 0.8f * dpi);

			if (icoWidget->m_WName.size()) {
				auto rect = icoWidget->f_getRect(true);
				rect.offset += coord;
				//f_vg_setLineText(self->m_画布, box.m_标签, icoWidget->m_WName, rect, E_对齐方式::e_左对齐, S_UI主题::uic_文字颜色);

				字符文本.push_back(icoWidget->m_WName);
				字符区域.push_back(rect);
				字符颜色.push_back(S_UI主题::uic_文字颜色);
			}
		}
		
		if (item->m_选中) {
			S_2DConvexRect rect;
			rect.offset = {};
			rect.size = e.m_W[i]->m_Size;
			rect.radius = {4,4};
			rect.AA_type = {0, 0};

			区域.push_back(rect);
			位置.push_back(coord);
			颜色.push_back(S_UI主题::uic_焦点色 * vec4{0.8,0.8,0.8,0.8} );
			形状.push_back(&((*self).m_UIctx->m_Ctx.m_几何图形->m_平面矩形));
		}


		if (!i) 开始推进 = item->m_层深度;

		coord = { item->m_层深度 * 行高, coord.y };
		coord.x += ico_offset;
		coord.y += 行高;
		box.m_直线坐标.push_back(coord);
		if (item->m_是否展开) {
			coord.y += 高度 * dpi;
		}
		box.m_直线坐标.push_back(coord);


		if (开始推进 > item->m_层深度) {
			uint32 空白线数量 = 开始推进 - item->m_层深度;

			for (uint32 i = 0; i < 空白线数量; ++i) {
				vec2 point = { (i + item->m_层深度) * 行高 + ico_offset, 0 };
				box.m_直线坐标.push_back(point);
				box.m_直线坐标.push_back({ point.x, coord.y - 行高 });
			}

			开始推进 = item->m_层深度;
		}
	}

	if (开始推进 > 0) {
		for (uint32 i = 0; i < 开始推进; ++i) {
			box.m_直线坐标.push_back({ i * 行高 + ico_offset, 0 });
			box.m_直线坐标.push_back({ i * 行高 + ico_offset, box.m_Size.y });
		}
	}

	switch (形状.size()) {
		case 0: break;
		case 1: {
			形状.front() = &((*self).m_UIctx->m_Ctx.m_几何图形->m_平面圆角矩形);
			break;
		}
		default: {
			形状.front() = &((*self).m_UIctx->m_Ctx.m_几何图形->m_平面上圆角矩形);
			形状.back() = &((*self).m_UIctx->m_Ctx.m_几何图形->m_平面下圆角矩形);
			break;
		}
	}
	


	f_vg_drawConvex(*box.m_背景, 形状.size(), 形状.data(), 区域.data());
	f_vg_tranform(*box.m_背景, 位置.size(), 位置.data());
	f_vg_color(*box.m_背景, 颜色.size(), 颜色.data());


	//f_vg_drawIco(*box.m_图标, 图标名称.size(), 图标名称.data());
	//f_vg_tranform(*box.m_图标, 图标位置.size(), 图标位置.data(), 图标大小.data());
	//f_vg_color(*box.m_图标, 图标颜色.size(), 图标颜色.data());

	
	f_vg_setLine(*box.m_线, box.m_直线坐标.size(), box.m_直线坐标.data(), 1.0);
	f_vg_tranform(*box.m_线, {});
	f_vg_color(*box.m_线, 1, &S_UI主题::uic_文字颜色 - 10);


	S_行字符串绘制属性 行字符串绘制属性 = { S_UI主题::ui_文字间隔 * dpi, E_方向::e_横向 };
	f_vg_drawString(*box.m_标签, 字符文本, 字符区域, 字符颜色, E_对齐方式::e_左对齐, 行字符串绘制属性);
	

	uint32 图标数量 = 图标名称.size();
	f_vg_drawIco(*box.m_图标, 图标数量, 图标名称.data());
	f_vg_tranform(*box.m_图标, 图标数量, 图标位置.data(), 图标大小.data());
	f_vg_color(*box.m_图标, 图标数量, 图标颜色.data());
}

static E_事件是否传递 f_树形框鼠标滚轮(C_Widget* self, const S_鼠标& 鼠标) {
	float32 内部高度 = f_ui_树形框_构建区域项显示(self);

	f_布局_纵向滚动值限度(self->m_Pos.y, self->m_父部件->m_Size.y, 内部高度, C_Widget::g_鼠标.lZ * 40);

	return E_事件是否传递::e_事件传递_终止;
}

C_树形框::C_树形框(S_UI渲染环境& ctx, S_Object* data) : C_Widget(&ctx), m_Data(data) {
	m_WName = u"树形框";
	m_TypeName = "C_Widget 树形框";

	mf_绘制 = f_树形框绘制;
	mf_布局 = f_树形框布局;
	mf_变换 = f_树形框变换修改;
	
	mf_自定义子项层级范围计算 = nullptr;
	mf_项附件组件创建 = nullptr;
	m_当前选择项 = nullptr;
	

	m_行高度 = 20;
	m_有效行数 = 0;
	m_当前选择项位置 = {};
	m_清除选项 = true;

	m_颜色A = S_UI主题::uic_列表行A;
	m_颜色B = S_UI主题::uic_列表行B;

	f_widget_开启视口属性(this);
	f_widget_添加绘制画布(this);

	if (m_Data) {
		m_引用数据 = true;
	}
	else {
		m_Data = new S_Object(E_物体类型::t_空);
		m_Data->m_是否展开 = true;
		m_引用数据 = false;
	}
}

C_树形框::~C_树形框() {
	if (!m_引用数据) {
		delete m_Data;
	}
}


C_Widget* f_ui_树形框_创建(S_UI渲染环境& ctx, S_Object* data) {
	C_树形框* box = new C_树形框(ctx, data);
	return box;
}

void f_ui_树形框_添加项(C_Widget* self) {
	auto& box = *static_cast<C_树形框*>(self);

	const float32 dpi = self->m_UIctx->m_DPI;
	float32 行高 = box.m_行高度 * dpi;
	uint32 组件数量 = self->m_Size.y / 行高 + 4; 

	uint32 num = self->f_get子部件数量();

	for (uint32 i = 组件数量; i < num; ++i) {
		self->f_添加子组件(new C_Widget);
	}
	//box.m_选择项.clear();
	//box.m_选择项组件.clear();
}


void f_ui_树形框_删除项(C_Widget* self) {

}

void f_ui_树形框_绑定回调函数(C_Widget* self, S_Object* data, fp_项层级计算 层级计算, fp_WidgetCall_CreateWidget 项子组件创建) {
	auto& box = *static_cast<C_树形框*>(self);

	box.mf_自定义子项层级范围计算 = 层级计算;
	box.mf_项附件组件创建 = 项子组件创建;

	box.m_Data = data;
	box.m_选择项.clear();

	f_widget_remove所有子部件(self);

	if(self->m_父部件) f_ui_树形框_构建区域项显示(self);
	f_树形框_重置选择项(&box, data);

	box.m_更新绘制属性 = true;
}

void f_ui_树形框_设置选择项(C_Widget* self, S_Object** data, uint32 num) {
	auto& box = *dynamic_cast<C_树形框*>(self);
	//box.m_选择项.clear();
	f_ui_树形框_清楚选择项(self);

	for (uint32 i = 0; i < num; ++i) {
		data[i]->f_选择(true);
		box.m_选择项.push_back(data[i]);
	}
}

void f_ui_树形框_设置区间选择项(C_Widget* self, C_Widget* item, S_Object** data, uint32 num) {
	auto& box = *dynamic_cast<C_树形框*>(self);

	if (!box.m_清除选项 && box.m_选择项.size() == 1 && num == 1 && item) {
		S_Object* item_begin;
		S_Object* item_end;

		bool 向下 = true;
		if (item->m_Pos.y >= box.m_当前选择项位置.y) {
			item_begin = box.m_当前选择项;
			item_end = data[0];
		}
		else {
			item_begin = data[0];
			item_end = box.m_当前选择项;
			向下 = false;
		}

		if (item_begin->m_父对象) {
			
			auto b = std::find(item_begin->m_父对象->m_子物体.begin(), item_begin->m_父对象->m_子物体.end(), item_begin);
			auto e = std::find(item_begin->m_父对象->m_子物体.begin(), item_begin->m_父对象->m_子物体.end(), item_end);

			if (e == item_begin->m_父对象->m_子物体.end()) {
				goto To_跨层级选择;
			}
			else {
				if (向下) {
					++b;
					++e;
				}
				
				if (b != item_begin->m_父对象->m_子物体.end()) {
					for (; b != e; ++b) {
						(*b)->m_选中 = true;
						box.m_选择项.push_back((*b));

						if ((*b)->m_是否展开) {
							if (f_树形框_项区间选择((*b), item_end)) {
								break;
							}
						}
					}
				}
			}
		}
		else {
			To_跨层级选择:
			item_begin->m_选中 = true;
			box.m_选择项.push_back(item_begin);

			auto b = item_begin->m_子物体.begin();
			auto e = item_begin->m_子物体.end();
			
			for (; b != e; ++b) {
				(*b)->m_选中 = true;
				box.m_选择项.push_back((*b));

				if((*b) == item_end) break;

				if ((*b)->m_是否展开) {
					if (f_树形框_项区间选择((*b), item_end)) {
						break;
					}
				}
			}
		}
	}
	else {
		f_ui_树形框_设置选择项(self, data, num);
	}

	if (item) {
		box.m_当前选择项位置 = item->m_Pos;
		box.m_当前选择项 = box.m_选择项.back();
	}
	
}

std::vector<S_Object*> f_ui_树形框_取选择项(C_Widget* self) {
	auto& box = *static_cast<C_树形框*>(self);
	return box.m_选择项;
}

void f_ui_树形框_删除选择项组件(C_Widget* self) {
	auto& box = *static_cast<C_树形框*>(self);

	auto e = self->f_get更新组件();
	for (uint32 i = 0; i < e.m_Num; ++i) {
		e.m_W[i]->m_UserData = nullptr;
		f_widget_remove所有子部件(e.m_W[i], false);
	}
}

//struct S_树形框数据添加池 {
//	S_Object*			m_root;
//	std::set<S_Object*> m_items;
//	std::set<C_Widget*> m_widget;
//};

static std::vector<S_树形框数据添加池> g树形框数据添加池;
static std::vector<S_树形框数据添加池> g树形框数据删除池;


//void f_ui_树形框_添加项(S_Object* root, std::set<S_Object*>& items, std::set<C_Widget*>& 树形框) {
//	g树形框数据添加池.push_back({root, items, 树形框});
//}
//void f_ui_树形框_删除项(S_Object* root, std::set<S_Object*>& items, std::set<C_Widget*>& 树形框) {
//	g树形框数据删除池.push_back({root, items, 树形框});
//}

void f_ui_树形框_添加项(S_Object* root, S_Object* items, const std::set<C_Widget*>& 树形框) {
	S_树形框数据添加池 item;
	item.m_root = root;
	item.m_items[items] = 树形框;
	g树形框数据添加池.push_back(item);
}
void f_ui_树形框_删除项(S_Object* root, S_Object* items, const std::set<C_Widget*>& 树形框) {
	S_树形框数据添加池 item;
	item.m_root = root;
	item.m_items[items] = 树形框;
	g树形框数据删除池.push_back(item);
}



void f_ui_树形框_更新数据添加() {
	std::set<C_树形框*> tree;

	for (auto& pack : g树形框数据添加池) {
		for (auto& e: pack.m_items) {
			for (auto& ws: e.second) {
				tree.insert(static_cast<C_树形框*>(ws));
			}
		}
	}
	
	for (auto& e : tree) {
		e->m_选择项.clear();
	}

	for (auto& pack : g树形框数据添加池) {
		
		for (auto& e: pack.m_items) {
			f_ob_push_back(pack.m_root, e.first);

			if(e.first->m_选中) {
				for (auto& ws: e.second) {
					static_cast<C_树形框*>(ws)->m_选择项.push_back(e.first);
					dynamic_cast<C_树形框*>(ws)->m_当前选择项 = e.first;
				}
			}
		}
	}


	for (auto& pack : g树形框数据删除池) {
		for (auto& e: pack.m_items) {
			for (auto& ws: e.second) {
				tree.insert(static_cast<C_树形框*>(ws));
			}
		}
	}
	
	for (auto& pack : g树形框数据删除池) {
		
		for (auto& e: pack.m_items) {
			auto it = std::find(pack.m_root->m_子物体.begin(), pack.m_root->m_子物体.end(), e.first);

			if (it != pack.m_root->m_子物体.end()) {
				(*it)->f_选择(false);
				pack.m_root->m_子物体.erase(it);
			}
		}
	}


	for (auto& e : tree) {
		f_ui_树形框_构建区域项显示(e);
		//f_widget_更新绘制(e);
	}


	//for (auto& pack : g树形框数据添加池) {
	//	std::vector<S_Object*> seleItem;
	//
	//	for (auto& e: pack.m_items) {
	//		f_ob_push_back(pack.m_root, e);
	//		if(e->m_选中) seleItem.push_back(e);
	//	}
	//	
	//	for (auto& e: pack.m_widget) {
	//		dynamic_cast<C_树形框*>(e)->m_选择项 = seleItem;
	//		dynamic_cast<C_树形框*>(e)->m_当前选择项 = seleItem.front();
	//
	//		f_ui_树形框_构建区域项显示(e);
	//		f_widget_更新绘制(e);
	//	}
	//}
	//for (auto& pack : g树形框数据删除池) {
	//	
	//	for (auto& e: pack.m_items) {
	//		auto it = std::find(pack.m_root->m_子物体.begin(), pack.m_root->m_子物体.end(), e);
	//
	//		if (it != pack.m_root->m_子物体.end()) {
	//			(*it)->f_选择(false);
	//			pack.m_root->m_子物体.erase(it);
	//		}
	//	}
	//
	//	for (auto& e: pack.m_widget) {
	//		f_ui_树形框_构建区域项显示(e);
	//		f_widget_更新绘制(e);
	//	}
	//}


	g树形框数据删除池.clear();
	g树形框数据添加池.clear();
}

void f_ui_树形框_清楚选择项(C_Widget* self) {
	auto& box = *static_cast<C_树形框*>(self);

	for (auto& e : box.m_选择项) {
		e->m_选中 = false;
	}
	box.m_选择项.clear();
	//box.m_选择项组件.clear();
}

void f_ui_树形框_关闭项选择清除(C_Widget* self, bool open) {
	auto& box = *static_cast<C_树形框*>(self);
	box.m_清除选项 = !open;
}




static C_Widget* g弹出列表面板 = nullptr;
static C_弹出列表编辑框* g当前操纵弹出列表编辑框 = nullptr;

static E_事件是否传递 on_弹出列表框鼠标进入(C_Widget* self, const S_鼠标& 鼠标) {
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_弹出列表框鼠标离开(C_Widget* self, const S_鼠标& 鼠标) {
	f_widget_线程定时关闭弹出组件();
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_弹出列表框项鼠标进入(C_Widget* self, const S_鼠标& 鼠标) {
	auto& box = *static_cast<C_弹出列表框*>(self->m_父部件);
	S_2DConvexRect rect;
	//S_GPU内存块* 元素 = &S_2D画布::g预设_圆角矩形;

	//f_vg_tranform(box.m_画布, {});

	//rect.offset = self->m_Pos;
	//rect.size = self->m_Size;
	//rect.radius = { S_UI主题::ui_面板圆角半径 * 1.5f, S_UI主题::ui_面板圆角半径 * 1.5f };
	//rect.AA_type = { f_PackData4X8(S_UI主题::uic_菜单背景), 0 };
	//f_vg_setElementRect(box.m_画布, box.m_高亮, 1, &元素, &rect);
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_弹出列表框项鼠标离开(C_Widget* self, const S_鼠标& 鼠标) {
	//self->m_颜色A = S_UI主题::uic_菜单背景 + S_RGBA8UI{20, 20, 20, 0};
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_弹出列表框项鼠标点击(C_Widget* self, const E_鼠标按钮& 鼠标) {
	auto& box = *static_cast<C_弹出列表框*>(self->m_父部件);

	f_prop_ObjectItem(g当前操纵弹出列表编辑框->m_自定义属性).当前选项 = self->m_WName;
	f_ui_set行编辑框文本(g当前操纵弹出列表编辑框->m_编辑框, self->m_WName);
	
	g当前操纵弹出列表编辑框->m_编辑框->m_颜色A = S_UI主题::uic_行编辑框背景;
	g当前操纵弹出列表编辑框->m_编辑框->m_更新绘制属性 = true;

	if (g当前操纵弹出列表编辑框->m_自定义属性.m_UI->m_Update) {
		g当前操纵弹出列表编辑框->m_自定义属性.m_UI->m_Update(g当前操纵弹出列表编辑框->m_自定义属性);
	}
	

	f_widget_顶层窗口_pop(f_ui_当前窗口管理(), 0);
	return E_事件是否传递::e_事件传递_终止;
}

static void f_弹出列表框绘制(C_Widget* self, S_2D画布* 画布) {
	auto& box = *dynamic_cast<C_弹出列表框*>(self);

	box.m_线 = f_vg_genLine(self->m_UIctx->m_Ctx, *画布, E_图层混合模式::e_Normal, E_线类型::e_线段);
	//box.m_背景 = f_vg_drawConvexElement(画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	box.m_标题 = f_vg_genString((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal, u"雅黑");
	box.m_图标 = f_vg_drawIco(画布, S_UI主题::ui_默认图标);
	//box.m_高亮 = f_vg_drawConvexElement(画布, E_填充模式::e_填充面, E_图层混合模式::e_Screen);
}

static void f_弹出列表框布局(C_Widget* self, C_Widget** w, uint32 num) {
	auto& box = *static_cast<C_弹出列表框*>(self);
	
	vec2 外框大小{ 100, 30 };
	vec2 项大小{80,20};
	if (num) {
		外框大小 = f_layout_网格排列({ 10,10 }, 项大小, {4,4}, w, num, 4);
		//for (uint32 i = 0; i < num; ++i) {
		//	w[i];
		//}
	}
	else {
		box.f_setPos({ 20, 20 });
		//box.f_setSize(self->m_Size - 40);
	}
	外框大小 += vec2{ 10, 10 } * 2;
	self->f_setSize(外框大小);

	f_widget_单个部件裁剪(self, { self->m_Pos.x, self->m_Pos.y, self->m_Pos.x + 外框大小.x, self->m_Pos.y + 外框大小.y }, {});
	//f_widget_单个部件裁剪(self, { 0, 0, self->m_Pos.x + 100, self->m_Pos.y + 30 }, {});
}

static void f_弹出列表框变换修改(C_Widget* self) {
	auto& box = *static_cast<C_弹出列表框*>(self);
	uint32 num = self->f_get子部件数量();

	auto e = self->f_get更新组件();
	//S_2DConvexRect rect[1];
	//S_GPU内存块* 元素[1];
	std::vector<S_2DConvexRect> rect(e.m_Num + 1);
	std::vector<S_GPU内存块*> 元素(e.m_Num + 1);

	f_vg_tranform(self->m_画布, {});
	//f_vg_text_tranform(self->m_画布, box.m_标题, {});
	//f_vg_lineText_begin(self->m_画布, box.m_标题);

	//rect[0].offset = {};
	//rect[0].size = self->m_Size;
	rect[0].radius = { S_UI主题::ui_面板圆角半径 * 1.5f, S_UI主题::ui_面板圆角半径 * 1.5f };
	rect[0].AA_type = { f_PackData4X8(S_UI主题::uic_菜单背景), 0 };
	元素[0] = &S_2D画布::g预设_圆角矩形;

	for (uint32 i = 0; i < e.m_Num; ++i) {
		//f_vg_setLineText(self->m_画布, box.m_标题, e.m_W[i]->m_WName, { e.m_W[i]->m_Pos, e.m_W[i]->m_Size }, E_对齐方式::e_据中对齐, S_UI主题::uic_文字颜色);

		//rect[i+1].offset = e.m_W[i]->m_Pos;
		//rect[i+1].size = e.m_W[i]->m_Size;
		rect[i+1].radius = { S_UI主题::ui_面板圆角半径 * 1.5f, S_UI主题::ui_面板圆角半径 * 1.5f };
		rect[i+1].AA_type = { f_PackData4X8(S_UI主题::uic_菜单背景 + S_RGBA8UI{20,20,20,0}), 0};
		元素[i+1] = &S_2D画布::g预设_圆角矩形;
	}
	//f_vg_setElementRect(self->m_画布, box.m_背景, e.m_Num+1, 元素.data(), rect.data());
}

C_弹出列表框::C_弹出列表框(S_UI渲染环境& ctx, E_布局方式 方式) : C_Widget(&ctx) {
	
	mf_绘制 = f_弹出列表框绘制;
	mf_布局 = f_弹出列表框布局;
	mf_变换 = f_弹出列表框变换修改;
	mf_鼠标进入 = on_弹出列表框鼠标进入;
	mf_鼠标离开 = on_弹出列表框鼠标离开;


	mf_项附件组件创建 = nullptr;

	m_颜色A = S_UI主题::uic_列表行A;
	m_颜色B = S_UI主题::uic_列表行B;

	f_widget_开启视口属性(this);
}

C_弹出列表框::~C_弹出列表框() {
	
}

void C_弹出列表框::f_绑定属性列表数据(S_Props& prop) {
	//m_列表 = prop;
	auto* 物体映射集 = f_prop_ObjectMap(prop);

	uint32 num = 0;
	auto e = f_get更新组件();

	if (物体映射集->容器) {
		num = 物体映射集->容器->size();

		for (uint32 i = e.m_Num; i < num; ++i) {
			C_Widget* item = new C_Widget;
			//item->m_WName = L"空选项";
			f_添加子组件(item);
		}
	}
	

	if (num) {
		f_widget_remove区间子组件(this, num, -1, true);
	}
	else {
		if (e.m_Num) {
			f_widget_remove区间子组件(this, 1, -1, true);
		}
		else {
			C_Widget* item = new C_Widget;
			item->m_WName = u"空选项";
			f_添加子组件(item);
		}
	}

	if (物体映射集->容器) {
		auto 子组件 = f_get更新组件();
		uint32 index = 0;
		for (auto& e : *物体映射集->容器) {
			子组件.m_W[index]->m_WName = e.first;
			子组件.m_W[index]->mf_鼠标进入 = on_弹出列表框项鼠标进入;
			子组件.m_W[index]->mf_鼠标离开 = on_弹出列表框项鼠标离开;
			子组件.m_W[index]->mf_鼠标点击 = on_弹出列表框项鼠标点击;

			++index;
		}
	}
}




static void on_弹出列表编辑框选择项名称编辑(S_Props& prop) {
	//std::cout<<"on_弹出列表编辑框选择项名称编辑 \n";
	auto& txt = f_prop_LineStr(prop);

	bool 是否有存在项 = false;
	auto* 当前操纵弹出列表编辑框 = dynamic_cast<C_弹出列表编辑框*>(prop.m_UI->m_部件->m_父部件);
	auto& item = f_prop_ObjectItem(当前操纵弹出列表编辑框->m_自定义属性);
	if (txt.size() && item.当前对象) {
		prop.m_UI->m_部件->m_颜色A = S_UI主题::uic_行编辑框背景;

		if (当前操纵弹出列表编辑框->m_自定义属性.m_UI->m_Update) {
			//修改键值
			item.当前选项 = txt;

			当前操纵弹出列表编辑框->m_自定义属性.m_UI->m_Update(当前操纵弹出列表编辑框->m_自定义属性);
		}
	}
	else {
		prop.m_UI->m_部件->m_颜色A = S_UI主题::uic_行编辑框背景;
	}
	
	f_widget_更新渲染层(prop.m_UI->m_部件);
	f_widget_更新渲染层(当前操纵弹出列表编辑框);
}

static E_事件是否传递 on_弹出列表编辑框左按钮单击(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_弹出列表编辑框* box = static_cast<C_弹出列表编辑框*>(self->m_父部件);
	C_按钮* but = static_cast<C_按钮*>(self);
	
	if (box->mf_项附件组件创建) {
		box->mf_项附件组件创建(*box->m_UIctx, box);

		auto& item = f_prop_ObjectItem(box->m_自定义属性);
		f_ui_set行编辑框文本(box->m_编辑框, item.当前选项);
		f_prop_LineStr(box->m_编辑文本) = item.当前选项;

		f_widget_更新渲染层(box);
	}

	return E_事件是否传递::e_事件传递_终止;
}
bool on_弹出列表编辑框菜单项点击(C_Widget* self, const std::u16string name, uint16 id) {
	if (g当前操纵弹出列表编辑框) {
		f_prop_ObjectSelect(g当前操纵弹出列表编辑框->m_自定义属性, name);

		if (g当前操纵弹出列表编辑框->m_自定义属性.m_UI->m_Update) {
			g当前操纵弹出列表编辑框->m_自定义属性.m_UI->m_Update(g当前操纵弹出列表编辑框->m_自定义属性);
		}

		f_widget_更新渲染层(g当前操纵弹出列表编辑框);
	}
	return false;
}

static E_事件是否传递 on_弹出列表编辑框_打开选择项菜单(C_Widget* self, const E_鼠标按钮& 按钮) {
	g当前操纵弹出列表编辑框 = dynamic_cast<C_弹出列表编辑框*>(self->m_父部件);

	S_菜单创建参数 menuItem{on_弹出列表编辑框菜单项点击};

	switch (g当前操纵弹出列表编辑框->m_自定义属性.m_Type) {
		case E_值类型::e_Type_ObjectContainerMap: {
			auto& obs = *f_prop_ObjectMap(g当前操纵弹出列表编辑框->m_自定义属性);
			if(!obs.容器) return E_事件是否传递::e_事件传递_终止;

			for (auto& e : *obs.容器) {
				menuItem.item.push_back({e.first, u"", u""});
			}
			break;
		}
		case E_值类型::e_Type_ObjectContainerArray: {
			auto& obs = *f_prop_ObjectArray(g当前操纵弹出列表编辑框->m_自定义属性);
			if(!obs.容器) return E_事件是否传递::e_事件传递_终止;

			for (auto& e : *obs.容器) {
				menuItem.item.push_back({e->m_Name, u"", u""});
			}
			//f_prop_ObjectArraySelect(prop, key);
			break;
		} 
	}
	

	vec2 pos = { self->m_裁剪大小.x, self->m_裁剪大小.y };
	g弹出列表面板->f_setSize({100,30});
	g弹出列表面板->f_setPos(pos);

	
	f_ui_填充菜单项(g弹出列表面板, menuItem);
	f_ui_打开弹出窗口(g弹出列表面板, pos, g当前操纵弹出列表编辑框);
	
	return E_事件是否传递::e_事件传递_终止;
}

static void f_弹出列表编辑框绘制(C_Widget* self, S_2D画布* 画布) {
	auto& box = *dynamic_cast<C_弹出列表编辑框*>(self);

	box.m_线 = f_vg_genLine(self->m_UIctx->m_Ctx, *画布, E_图层混合模式::e_Normal, E_线类型::e_线段);
	box.m_标签 = f_vg_genString((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal, u"雅黑");
	box.m_图标 = f_vg_drawIco(画布, S_UI主题::ui_默认图标);
	//box.m_高亮 = f_vg_drawConvexElement(画布, E_填充模式::e_填充面, E_图层混合模式::e_Screen);
}

static void f_弹出列表编辑框布局(C_Widget* self, C_Widget** w, uint32 num) {
	auto& box = *static_cast<C_弹出列表编辑框*>(self);
	
	vec2 size = {self->m_Size.y, self->m_Size.y};
	w[0]->f_setSize(size);
	w[1]->f_setSize({ self->m_Size.x - size.x*2, self->m_Size.y });
	w[2]->f_setSize(size);

	w[0]->f_setPos({});
	w[1]->f_setPos({ size.x, 0 });
	w[2]->f_setPos({ self->m_Size.x - size.x, 0 });
}

static void f_弹出列表编辑框变换修改(C_Widget* self) {
	C_弹出列表编辑框& box = *static_cast<C_弹出列表编辑框*>(self);
	uint32 num = self->f_get子部件数量();
}

C_弹出列表编辑框::C_弹出列表编辑框(S_UI渲染环境& ctx) : C_Widget(&ctx) {
	//mf_DrawFun = f_树形框绘制;
	mf_布局 = f_弹出列表编辑框布局;
	//mf_变换修改 = f_树形框变换修改;
	//mf_鼠标滚轮 = f_树形框鼠标滚轮;
	//mf_鼠标离开 = on_树形框鼠标离开;
	f_setSize({20,20});

	m_颜色A = S_UI主题::uic_列表行A;
	m_颜色B = S_UI主题::uic_列表行B;

	m_编辑文本 = f_alloc_LineStrProp(nullptr, u"编辑文本");
	m_编辑文本.m_私有 = true;
	m_编辑文本.m_UI->m_Update = on_弹出列表编辑框选择项名称编辑;

	m_拾取按钮 = new C_按钮(&ctx);
	m_菜单按钮 = new C_按钮(&ctx);

	auto* 编辑框 = new C_行编辑框(ctx);
	编辑框->m_对齐方式 = E_对齐方式::e_据中对齐;
	编辑框->f_bind属性(m_编辑文本);
	m_编辑文本.m_UI->m_部件 = 编辑框;
	m_编辑框 = 编辑框;
	
	m_拾取按钮->m_图元形状 = &(m_UIctx->m_Ctx.m_几何图形->m_平面左圆角矩形);
	m_拾取按钮->m_ColorA = S_UI主题::uic_按钮;
	m_拾取按钮->mf_鼠标点击 = on_弹出列表编辑框左按钮单击;

	m_编辑框->m_图元形状 = &(m_UIctx->m_Ctx.m_几何图形->m_平面矩形);
	m_编辑框->m_ColorA = S_UI主题::uic_行编辑框背景;
	m_菜单按钮->m_图元形状 = &(m_UIctx->m_Ctx.m_几何图形->m_平面右圆角矩形);
	m_菜单按钮->m_ColorA = S_UI主题::uic_按钮;
	m_菜单按钮->mf_鼠标点击 = on_弹出列表编辑框_打开选择项菜单;

	m_拾取按钮->m_ICO = u"点击";
	m_编辑框->m_ICO = u"点击";
	m_菜单按钮->m_ICO = u"下";
	

	f_添加子组件(m_拾取按钮);
	f_添加子组件(m_编辑框);
	f_添加子组件(m_菜单按钮);


	if (!g弹出列表面板) {
		g弹出列表面板 = f_ui_创建菜单(ctx, E_方向::e_纵向);
		//g弹出列表面板 = new C_弹出列表框(ctx);
	}

}

C_弹出列表编辑框::~C_弹出列表编辑框() {
	f_prop_Release(m_编辑文本);
}

C_Widget* f_ui_创建弹出列表编辑框(S_UI渲染环境& ctx, fp_WidgetCall_CreateWidget 项创建回调, bool 创建点选) {
	C_弹出列表编辑框* box = new C_弹出列表编辑框(ctx);

	box->mf_项附件组件创建 = 项创建回调;
	box->m_拾取按钮;

	return box;
}

void f_ui_弹出列表编辑框绑定数据(C_Widget* self, S_Props& prop, fp_WidgetCall_CreateWidget 项创建回调) {
	C_弹出列表编辑框* box = dynamic_cast<C_弹出列表编辑框*>(self);

	box->mf_项附件组件创建 = 项创建回调;
	box->m_自定义属性 = prop;
	auto name = f_prop_ObjectItem(prop).当前选项;

	f_ui_set行编辑框文本(box->m_编辑框, name);
	f_prop_LineStr(box->m_编辑文本) = name;
}




